﻿using FastMvc.Exceptions;
using FastMvc.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace FastMvc.MiddleWare
{
    /// <summary>
    /// 异常检查中间件
    /// * 处于所有中间件的最外层, 处理异常捕获，日志记录，对外接口的友好化
    /// </summary>
    public class ExceptionHandlerMiddleware
    {
        private readonly RequestDelegate next;
        public ExceptionHandlerMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            try
            {
                await next.Invoke(context);

            }
            catch (UnAuthException ue)
            {
                int statusCode = 406;
                if (ue.NeedLogin)
                    statusCode = 401; // 无授权，需要登录

                await SetExceptionResult(context, statusCode, -1, ue.Message);
            }
            catch (ApiException ae)
            {
                await SetExceptionResult(context, 200, ae.Code, ae.Message, ae.Errors);
            }
            catch (System.Exception se)
            {
                await SetExceptionResult(context, 500, -1, "系统内部错误！", new List<ErrorMsg>() { new ErrorMsg() { parameter = "message", message = se.Message } });
            }
        }

        private async Task SetExceptionResult(HttpContext context, int statusCode, int errCode, string message, List<ErrorMsg> errors = null)
        {
            context.Response.StatusCode = statusCode;
            var result = JsonConvert.SerializeObject(new BaseResult() { success = false, code = errCode, message = message, Errors = errors });
            context.Response.ContentType = "application/json;charset=utf-8";
            await context.Response.WriteAsync(result);
        }
    }

    public static class ExceptionHandlerMiddlewareExt
    {
        public static IApplicationBuilder UseFMExceptionHandler(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ExceptionHandlerMiddleware>();
        }
    }
}
